package fp.poczadly.client;

import java.util.List;

import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;

import fp.poczadly.client.event.LoginEvent;
import fp.poczadly.client.event.LoginEventHandler;
import fp.poczadly.client.event.LogoutEvent;
import fp.poczadly.client.event.LogoutEventHandler;
import fp.poczadly.client.event.PrivateMessageEvent;
import fp.poczadly.client.event.PrivateMessageEventHandler;
import fp.poczadly.client.event.ReceivePrivateMessageEvent;
import fp.poczadly.client.event.ReceivePrivateMessageEventHandler;
import fp.poczadly.client.presenter.ChatPresenter;
import fp.poczadly.client.presenter.LoginPresenter;
import fp.poczadly.client.presenter.Presenter;
import fp.poczadly.client.presenter.PrivateMessagePresenter;
import fp.poczadly.client.view.ChatView;
import fp.poczadly.client.view.LoginView;
import fp.poczadly.client.view.PrivateMessageView;
import fp.poczadly.shared.Message;
import fp.poczadly.shared.User;
import fp.poczadly.shared.Utils;

public class AppController {

	public enum Presenters {
		LOGIN,
		CHAT,
		PRIVATE_MESSAGE
	}
	
	private HasWidgets container;
	private LiveChatServiceAsync rpcService;
	private HandlerManager eventBus;
	
	private User user;
	
	public AppController( LiveChatServiceAsync rpcService, HandlerManager eventBus ) {
		this.eventBus = eventBus;
		this.rpcService = rpcService;
		
		bind();
	}
	
	protected void bind() {
		eventBus.addHandler( LoginEvent.TYPE, new LoginEventHandler() {

			@Override
			public void addUser( LoginEvent event ) {
				try {
					user = event.getLoggedUser();
					
					ChatPresenter chatPresenter = (ChatPresenter) changePresenter( Presenters.CHAT );
					chatPresenter.go( container );
					ChatPresenter.setPrivMessage( false );
				} catch( NullPointerException e ) {
					changePresenter( Presenters.LOGIN ).go( container );
				}
			}
		} );
		
		eventBus.addHandler( LogoutEvent.TYPE, new LogoutEventHandler() {
			
			@Override
			public void removeUser( LogoutEvent event ) {
				try {
					Window.alert( Utils.GOOD_BYE_MESSAGE + user.getUsername() );
					
					changePresenter( Presenters.LOGIN ).go( container );
				} catch( NullPointerException ex ) {
					Window.alert( Utils.CANNOT_REMOVE_USER );
				}
			}
		} );
		
		eventBus.addHandler( PrivateMessageEvent.TYPE, new PrivateMessageEventHandler() {
			
			@Override
			public void openPrivateMessageView( PrivateMessageEvent event ) {
				final PrivateMessagePresenter privateMessagePresenter = (PrivateMessagePresenter) changePresenter( Presenters.PRIVATE_MESSAGE );
				
				rpcService.getSelectedUser( event.getUsername(), new AsyncCallback<User>() {
					
					@Override
					public void onSuccess( User result ) {
						privateMessagePresenter.setToUser( result );
						privateMessagePresenter.go( container );
					}
					
					@Override
					public void onFailure( Throwable caught ) {
						Window.alert( Utils.CANNOT_FIND_USER );
					}
				} );
			}
		} );
		
		eventBus.addHandler( ReceivePrivateMessageEvent.TYPE, new ReceivePrivateMessageEventHandler() {

			@Override
			public void receivePrivateMessage( ReceivePrivateMessageEvent event ) {
				rpcService.receivePrivateMessages( user, new AsyncCallback<List<Message>>() {

					@Override
					public void onFailure( Throwable caught ) {
						System.out.println( "On failure" );
					}

					@Override
					public void onSuccess( List<Message> result ) {
						User fromUser = null;
						
						for( Message m : result ) {
							fromUser = m.getFrom();
						}
						
						if( fromUser != null ) {
							PrivateMessagePresenter privateMessagePresenter = (PrivateMessagePresenter) changePresenter( Presenters.PRIVATE_MESSAGE );
							privateMessagePresenter.setFromUser( fromUser );
							privateMessagePresenter.setToUser( user );
							privateMessagePresenter.go( container );
						}
					}
				} );
			}
			
		} );
	}
	
	public void go( HasWidgets container ) {
		this.container = container;
		
		changePresenter( Presenters.LOGIN ).go( container );
	}
	
	public Presenter changePresenter( Presenters presenter ) {
		switch( presenter ) {
		case LOGIN:
			return new LoginPresenter( rpcService, eventBus, new LoginView() );

		case CHAT:
			return new ChatPresenter( rpcService, eventBus, user, new ChatView() );
			
		case PRIVATE_MESSAGE:
			return new PrivateMessagePresenter( rpcService, eventBus, user, new PrivateMessageView() );
			
		default:
			throw new IllegalArgumentException();
		}
	}
	
}
